package com.jie.other.jetpack.paging.indb

import androidx.paging.ExperimentalPagingApi
import androidx.paging.LoadType
import androidx.paging.PagingState
import androidx.paging.RemoteMediator
import androidx.room.withTransaction
import com.blankj.utilcode.util.LogUtils
import com.jie.other.jetpack.paging.bean.DataPage
import com.jie.other.jetpack.paging.bean.Repo
import com.jie.other.jetpack.paging.inhttp.GithubService
import com.jie.other.jetpack.paging.inhttp.HttpPagingSource
import com.jie.other.jetpack.room.AppDataBase
import com.net.okhttphelper.http.ExceptionHandle

/**
 * 将服务器的数据存储到本地数据库中，当页面监听到数据库中数据发生改变时，自动刷新列表
 */
@OptIn(ExperimentalPagingApi::class)
class DBRemoteMediator(private val dataBase: AppDataBase,
                       private val httpService: GithubService
) : RemoteMediator<Int, Repo>() {

    companion object{
        const val DATA_PAGE_ID_PAGING = "DATA_PAGE_ID_PAGING"
    }

    private val mDataPageDao = dataBase.getDataPageDao()
    private val mRepoDao = dataBase.getRepoDao()

    override suspend fun initialize(): InitializeAction {
        return super.initialize()
    }

    override suspend fun load(loadType: LoadType, state: PagingState<Int, Repo>): MediatorResult {
        try {
            val nextPageKey = when(loadType) {
                LoadType.REFRESH -> null
                LoadType.PREPEND -> return MediatorResult.Success(endOfPaginationReached = true)
                LoadType.APPEND -> {
                    val dataPage = dataBase.withTransaction {
                        mDataPageDao.getDataPage(DATA_PAGE_ID_PAGING)
                    }
                    if (dataPage?.nextPageKey == null) {
                        return MediatorResult.Success(endOfPaginationReached = true)
                    } else {
                        dataPage.nextPageKey
                    }
                }
            }?: HttpPagingSource.FIRST_PAGE_NUM
            val pageSize = if (loadType == LoadType.REFRESH) {
                state.config.initialLoadSize
            } else {
                state.config.pageSize
            }
            val response = httpService.searchRepos(HttpPagingSource.QUERY_KEY,
                nextPageKey, pageSize)
            val items = response.items
            // 计算下个页面pageNum
            val afterPageKey = if (items.isEmpty()) {
                null
            } else {
                // 由于第一次加载会默认加载 3 * pageSize，故需要做如下处理
                pageSize / state.config.pageSize + nextPageKey
            }
            dataBase.withTransaction {
                if (loadType == LoadType.REFRESH) {
                    mRepoDao.deleteAll()
                    mDataPageDao.delete(DATA_PAGE_ID_PAGING)
                }
                mDataPageDao.insert(DataPage(dataPageId = DATA_PAGE_ID_PAGING, afterPageKey))
                mRepoDao.insertList(items)
            }
            return MediatorResult.Success(endOfPaginationReached = items.isEmpty())
        } catch (e : Exception) {
            LogUtils.i("数据来源出错：${e}")
            return MediatorResult.Error(Throwable(ExceptionHandle.handlerException(e)))
        }
    }
}